package cn.jiedh.app.meiweidk.web;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Environment;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

import com.tencent.smtt.sdk.WebSettings;
import com.tencent.smtt.sdk.WebView;
import com.tencent.smtt.sdk.WebViewClient;
import cn.jiedh.app.meiweidk.web.webhandle.OpenUrlHandle;
import cn.jiedh.app.meiweidk.web.webhandle.PushToLoanDetailHandle;
import cn.jiedh.app.meiweidk.web.webhandle.RecordEventHandle;
import cn.jiedh.app.meiweidk.web.webhandle.ShareHandle;
import cn.jiedh.app.meiweidk.web.webhandle.ShowMsgHandle;
import cn.jiedh.app.meiweidk.web.webhandle.TranslateDataHandle;
import cn.jiedh.app.meiweidk.web.webhandle.UmengHandle;
import cn.jiedh.app.meiweidk.web.webkit.WJBridgeHandler;
import cn.jiedh.app.meiweidk.web.webkit.WJBridgeProvider;
import cn.jiedh.app.meiweidk.web.webkit.WJBridgeX5WebViewClient;
import cn.jiedh.app.meiweidk.web.webkit.WJCallbacks;
import cn.jiedh.app.meiweidk.web.webkit.WJMessage;
import cn.jiedh.app.meiweidk.web.webkit.WJWebLoader;
import cn.jiedh.app.meiweidk.web.webkit.WebViewJavascriptBridge;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Locale;

/**
 * @name：
 * @author： liuyun
 * @phone： 15723310658
 * @createTime： 2017/7/21
 * @modifyTime： 2017/7/21
 * @explain：说明
 */


public class CommonWebView extends WebView implements WebViewJavascriptBridge,WJWebLoader {
    private static final String TAG = "CommonWebView";
    private View mErrorView;
    private boolean mHasPostHideError;
    private OnScrollChangedListener mOnScrollChangedListener;
    private int mNextAction = -1;
    private boolean mIsErrorOccurred;
    private ILoading mLoading;
    private boolean mIsLoading;

    private int mOverScrollByDeltaX;
    private int mOverScrollByDeltaY;

    private boolean mHasDestroy = false;
    private WJBridgeProvider mProvider;
    private WJBridgeX5WebViewClient wjBridgeX5WebViewClient;
    private Runnable mHideErrorRunnable = new Runnable() {
        @Override
        public void run() {
            mErrorView.setVisibility(View.GONE);
            mHasPostHideError = false;
        }
    };

    public CommonWebView(Context context) {
        super(context);
        setup(context);
    }

    public CommonWebView(Context context, AttributeSet attrs) {
        super(context, attrs);
        setup(context);
    }

    public CommonWebView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        setup(context);
    }

    @SuppressLint("SetJavaScriptEnabled")
    private void setup(Context context) {
        this.mProvider = WJBridgeProvider.newInstance(this);
        WebSettings setting = this.getSettings();
        setting.setJavaScriptEnabled(true);
        setting.setSupportZoom(true);
        setting.setBuiltInZoomControls(true);
        String userAgent = setting.getUserAgentString() + " " + getCustomUserAgent(context);
        setting.setUserAgentString(userAgent);

        //setting.setSupportMultipleWindows(true);
        callSettingMethod(setting, "setDisplayZoomControls", false);

        callSettingMethod(setting, "setDomStorageEnabled", true);
        callSettingMethod(setting, "setDatabaseEnabled", true);
        String dataBasePath = context.getFilesDir().getPath() + context.getPackageName() + "/databases/";

        callSettingMethod(setting, "setDatabasePath", dataBasePath);
        //callSettingMethod(setting, "setAppCacheMaxSize", 1024 * 1024 * 8L);
        callSettingMethod(setting, "setAppCachePath", getCacheDir().getAbsolutePath());
        callSettingMethod(setting, "setAppCacheEnabled", true);
        // Enable location
        callSettingMethod(setting, "setGeolocationEnabled", true);
        callSettingMethod(setting, "setGeolocationDatabasePath", dataBasePath);

        //this.setWebViewClient(new DefaultWebViewClient());
        //this.setWebChromeClient(new DefaultWebChromeClient());


        this.setVerticalScrollBarEnabled(false);
        this.setHorizontalScrollBarEnabled(false);
        this.getSettings().setJavaScriptEnabled(true);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            android.webkit.WebView.setWebContentsDebuggingEnabled(true);
        }
        wjBridgeX5WebViewClient=onCreateWebViewClient(mProvider);
        this.setWebViewClient(wjBridgeX5WebViewClient);

        registerHandler(TranslateDataHandle.HANDLE_NAME,new TranslateDataHandle(getContext()));
        registerHandler(OpenUrlHandle.HANDLE_NAME,new OpenUrlHandle(getContext()));
        registerHandler(ShareHandle.HANDLE_NAME,new ShareHandle(getContext()));
        registerHandler(RecordEventHandle.HANDLE_NAME,new RecordEventHandle(getContext()));
        registerHandler(ShowMsgHandle.HANDLE_NAME,new ShowMsgHandle(getContext()));
        registerHandler(PushToLoanDetailHandle.HANDLE_NAME,new PushToLoanDetailHandle(getContext()));
        registerHandler(UmengHandle.HANDLE_NAME,new UmengHandle(getContext()));
    }
    public void setCustomWebViewClient(WebViewClient webViewClient){
        wjBridgeX5WebViewClient.setWebViewClient(webViewClient);
    }
    protected WJBridgeX5WebViewClient onCreateWebViewClient(WJBridgeProvider provider){
        return new WJBridgeX5WebViewClient(provider);
    }
    public static String getCustomUserAgent(Context cxt) {
        String sVersionName="";
        PackageManager manager = cxt.getPackageManager();
        int versionCode = -1;
        try {
            PackageInfo info = manager.getPackageInfo(cxt.getPackageName(), 0);
//                    sVersionCode = info.versionCode;
            sVersionName = info.versionName;
        } catch (PackageManager.NameNotFoundException e) {
        }


        return "Terminus/" + sVersionName + " " + "lan/" + getLanguage(cxt);
    }
    public static String getLanguage(Context context) {
        Locale locale = context.getResources().getConfiguration().locale;
        String language = locale.getLanguage().toLowerCase(locale);
        String country = locale.getCountry().toLowerCase(locale);
        if (TextUtils.isEmpty(country)) {
            return language;
        } else {
            return language + "_" + country;
        }
    }
    private void callSettingMethod(WebSettings setting, String name, boolean val) {
        try {
            Method method = setting.getClass().getMethod(name, boolean.class);
            method.invoke(setting, val);
        } catch (NoSuchMethodException e) {

        } catch (IllegalAccessException e) {

        } catch (InvocationTargetException e) {

        } catch (Exception e) {

        }
    }

    private void callSettingMethod(WebSettings setting, String name, String val) {
        try {
            Method method = setting.getClass().getMethod(name, String.class);
            method.invoke(setting, val);
        } catch (NoSuchMethodException e) {

        } catch (IllegalAccessException e) {

        } catch (InvocationTargetException e) {

        } catch (Exception e) {

        }
    }

    private void callSettingMethod(WebSettings setting, String name, long val) {
        try {
            Method method = setting.getClass().getMethod(name, long.class);
            method.invoke(setting, val);
        } catch (NoSuchMethodException e) {

        } catch (IllegalAccessException e) {

        } catch (InvocationTargetException e) {

        } catch (Exception e) {

        }
    }

    private void callHiddenWebViewMethod(String name) {

        try {
            Method method = WebView.class.getMethod(name);
            method.invoke(this);
        } catch (NoSuchMethodException e) {

        } catch (IllegalAccessException e) {

        } catch (InvocationTargetException e) {

        } catch (Exception e) {

        }
    }

    public void safeOnResume() {
        callHiddenWebViewMethod("onResume");
    }


    public void safeOnPause() {
        callHiddenWebViewMethod("onPause");
    }

    public File getCacheDir() {
        return getDiskCacheDir(getContext(), "webview");
    }
    public static File getDiskCacheDir(Context context, String uniqueName) {
        File appCacheDir = getCacheDirectory(context, true);
        File individualCacheDir = new File(appCacheDir, uniqueName);
        if (!individualCacheDir.exists()) {
            if (!individualCacheDir.mkdir()) {
                individualCacheDir = appCacheDir;
            }
        }
        return individualCacheDir;
    }
    public static File getCacheDirectory(Context context, boolean preferExternal) {
        File appCacheDir = null;
        String externalStorageState;
        try {
            externalStorageState = Environment.getExternalStorageState();
        } catch (NullPointerException e) { // (sh)it happens (Issue #660)
            externalStorageState = "";
        }
        if (preferExternal) {
//            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.GINGERBREAD) {
//                if (Environment.MEDIA_MOUNTED.equals(externalStorageState)
//                        || !Environment.isExternalStorageRemovable()) {
//                    appCacheDir = getExternalCacheDir(context);
//                }
//            } else {
//                if (Environment.MEDIA_MOUNTED.equals(externalStorageState)) {
//                    appCacheDir = getExternalCacheDir(context);
//                }
//            }
            if (Environment.MEDIA_MOUNTED.equals(externalStorageState)) {
                appCacheDir = getExternalCacheDir(context);
            }
        }
        if (appCacheDir == null) {
            appCacheDir = context.getCacheDir();
        }
        if (appCacheDir == null) {
            String cacheDirPath = "/data/data/" + context.getPackageName() + "/cache/";
            appCacheDir = new File(cacheDirPath);
        }
        return appCacheDir;
    }

    private static File getExternalCacheDir(Context context) {
        File appCacheDir = context.getExternalCacheDir();
        if (appCacheDir != null && !appCacheDir.exists()) {
            if (!appCacheDir.mkdirs()) {
                return null;
            }
            ensureFileExists(new File(appCacheDir, ".nomedia"));
        }
        return appCacheDir;
    }
    public static void ensureFileExists(File file) {
        if (file == null || file.exists()) {
            return;
        }

        try {
            if (!file.createNewFile()) {
                throw new IOException();
            }
        } catch (IOException e) {
            Log.w(TAG, new RuntimeException("Creating file has failed: " + file.getAbsolutePath(), e));
        }
    }
    public void refresh() {
        reload();
        //loadUrl("javascript:window.location.reload( true )");
    }

    public View getErrorView() {
        return mErrorView;
    }

    public void setErrorView(View errorView) {
        mErrorView = errorView;
        if (mIsErrorOccurred) {
            showErrorView();
        } else if (mErrorView != null) {
            mErrorView.setVisibility(View.GONE);
        }
    }

    public boolean isShowError() {
        return (mErrorView != null && mErrorView.getVisibility() == View.VISIBLE);
    }

    public void showErrorView() {
        // if we are using system web view, use our defined error view, else use uc core default error view
        mIsErrorOccurred = true;
        if (mErrorView != null) {
            removeHideErrorCallback();
            mErrorView.setVisibility(View.VISIBLE);
        }
    }

    public void hideErrorView() {
        mIsErrorOccurred = false;
        if (mErrorView != null
                && (mErrorView.getVisibility() == View.VISIBLE) && !mHasPostHideError) {
            mHasPostHideError = true;
            mErrorView.postDelayed(mHideErrorRunnable, 500);
        }
    }

    public void setOnScrollChangedListener(OnScrollChangedListener l) {
        mOnScrollChangedListener = l;
    }

    public void startLoadingProgress() {
        if (mLoading != null) {
            mLoading.start();
        }
        mIsLoading = true;
    }

    public void stopLoadingProgress() {
        if (mLoading != null) {
            mLoading.stop();
        }
        mIsLoading = false;
    }

    public boolean isLoading() {
        return mIsLoading;
    }

    public void setLoading(ILoading loading) {
        mLoading = loading;
        if (mLoading != null) {
            if (mIsLoading) {
                mLoading.start();
            } else {
                mLoading.stopImmediately();
            }
        }
    }

    private void removeHideErrorCallback() {
        if (mErrorView != null) {
            mErrorView.removeCallbacks(mHideErrorRunnable);
            mHasPostHideError = false;
        }
    }

    @Override
    public void onScrollChanged(final int l, final int t, final int oldl, final int oldt) {
        super.onScrollChanged(l, t, oldl, oldt);
        if (mOnScrollChangedListener != null) {
            mOnScrollChangedListener.onScrollChanged(this, l, t, oldl, oldt);
        }
    }

    @Override
    public boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX, int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) {
        this.mOverScrollByDeltaX = deltaX;
        this.mOverScrollByDeltaY = deltaY;
        final boolean result = super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX, scrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent);
        return result;
    }

    @Override
    protected void onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY) {
        super.onOverScrolled(scrollX, scrollY, clampedX, clampedY);
        if (mOnScrollChangedListener != null && (clampedX || clampedY)) {
            mOnScrollChangedListener.onOverScrolled(this, mOverScrollByDeltaX, mOverScrollByDeltaY, clampedX, clampedY);
        }
    }

    @Override
    public void destroy() {
        if (!mHasDestroy) {
            removeHideErrorCallback();
            setWebViewClient(null);
            setWebChromeClient(null);
            super.destroy();
            mHasDestroy = true;
        }
        this.mProvider.destroy();
    }

    private void postAction(int action) {
        mNextAction = action;
    }

    @Override
    public void send(String data) {
        this.mProvider.send(data);
    }

    @Override
    public void send(String data, WJCallbacks callbacks) {
        this.mProvider.send(data,callbacks);
    }

    @Override
    public void setStartupMessages(List<WJMessage> messages) {
        this.mProvider.setStartupMessages(messages);
    }

    @Override
    public void loadUrl(String jsUrl, WJCallbacks callbacks) {
        this.mProvider.loadUrl(jsUrl,callbacks);
    }

    @Override
    public void callHandler(String handlerName, String data, WJCallbacks callbacks) {
        this.mProvider.callHandler(handlerName,data,callbacks);
    }

    @Override
    public void registerHandler(String handlerName, WJBridgeHandler handler) {
        this.mProvider.registerHandler(handlerName,handler);
    }

    @Override
    public void setDefaultHandler(WJBridgeHandler handler) {
        this.mProvider.setDefaultHandler(handler);
    }

}
